#!/usr/bin/env python
# encoding: utf-8
import glob,os
from pathlib import Path
from nb_log import get_logger

# import nltk
# nltk.download('punkt')

# 每次程序启动，自动检查最外城的动态配置路径是否创建，没有创建则自动创建该目录
# 因为gunicorn启动和python直接启动的路径获取的值有差异，为了保证准确性，按找次方法获取项目最外层路径
# dynamic_conf_dir = Path(__file__).parent/'../../'/'featurelib_dynamic_conf'
# if not dynamic_conf_dir.exists():
#     try:
#         dynamic_conf_dir.mkdir()
#     except FileExistsError:
#         pass

# def check_refresh_conf(path_pattern, conf_dict, load_fun):
#     """
#     根据路径的表达式，自动判断并加载最新的配置文件，如果想要使用该功能请标准化命名,采用 '固定前缀+日期' 的方式命名配置文件,如'app_rlevel_mx20240613'
#     每次判断当前的配置文件，是不是最新的，如果不是最新的则重新加载配置文件。
#     :param path_pattern: 使用glob.glob 表达式的标准路径方式 './conf/app_rlevel_mx*.xlsx'
#     :param conf_dict: 待刷新的配置文件所在的dict
#     :return:
#     """
#     # 获取最新的文件名称，一定要采用规范的方式命名才能正确检测最新的文件
#     # todo 判断的时候剔除带lock的标记
#     newest_file_name = sorted(glob.glob(path_pattern))[-1]
#     if conf_dict is None or newest_file_name > conf_dict['file_name']:
#         return {
#             'file_name': newest_file_name,
#             'conf': load_fun(newest_file_name)
#         }
#     else:
#         return conf_dict


class RequstData:
    def __init__(self):
        self.nid = ""
        self.country_code = ""
        self.country_abbr=""
        self.merchant_id = ""
        self.tx_id = ""
        self.order_id = ""
        self.phone = ""
        self.nid = ""
        self.source = 0
        self.acq_channel = ""
        self.device_type = "android"
        self.app_user_id = ""
        self.apply_time = ""
        self.track_id = ""
        self.data_sources = {}
        self.features = {}
        self.models = {}


class BaseFeature:
    """
    计算函数的基础父类
    """
    logger = get_logger(None)
    sms_conf_dir = Path(__file__).parent.parent / 'feature_conf' / 'sms'
    app_conf_dir = Path(__file__).parent.parent / 'feature_conf' / 'app'
    call_conf_dir = Path(__file__).parent.parent / 'feature_conf' / 'call'
    dynamic_conf  = Path(__file__).parent.parent/'dynamic_conf'

    def __init__(self):
        """
        父类的构造器，建议在继承的子类中显示的调用,初始化了logger对象，以及各组配置文件的基本路径
        """
        # 每个实例有一个自己的function_map来初始化自己的方法流程
        self.function_map = {}
        self.data = None
        self.conf = None

    def load_conf(self):
        """
        加载配置文件的函数，需要手动在_init_函数中调用，需要自己亲自实现
        """
        raise NotImplementedError("每个子类实现自己的配置加载方式,并自己设置好对应的function_map")

    def load_request(self, request_data: RequstData):
        """
        装载数据的函数，将数据初始化并挂载到计算对象身上的函数，每次请求都会单独调用，需要自己亲自实现
        """
        raise NotImplementedError("每个子类实现自己的配置加载方式,并自己设置好对应的function_map")

    def gen_features(self, data: RequstData):
        """
        为generator装载数据，并遍调用function_map中的函数，收集并整理计算后的结果，如需要增加特征名称前缀，请在子类中自行实现
        """
        self.load_request(data)
        rs_dict = {}
        for k, func in self.function_map.items():
            rs_dict.update(func())

        for k, v in rs_dict.items():
            if rs_dict[k] and type(rs_dict[k]) != str:
                rs_dict[k] = round(rs_dict[k], 4)
            else:
                continue
        return rs_dict
